<template>
  <el-dialog
    v-model="dialogVisible"
    title="文件预览"
    width="80%"
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <div v-if="file" class="preview-container">
      <div class="preview-header">
        <h3>{{ file.originalName }}</h3>
        <div class="preview-actions">
          <el-button @click="handleDownload" :icon="Download">
            下载
          </el-button>
          <el-button @click="handleShare" :icon="Share">
            分享
          </el-button>
        </div>
      </div>
      
      <div class="preview-content">
        <div v-if="file.canPreview" class="preview-area">
          <!-- 图片预览 -->
          <img
            v-if="file.fileType === 'image' && imageUrl"
            :src="imageUrl"
            :alt="file.originalName"
            class="preview-image"
            @load="handleImageLoad"
            @error="handleImageError"
          />
          <div v-else-if="file.fileType === 'image' && !imageUrl" class="loading">
            <el-icon class="is-loading"><Loading /></el-icon>
            <p>加载中...</p>
          </div>
          
          <!-- PDF预览 -->
          <iframe
            v-if="file.fileType === 'document' && file.originalName.toLowerCase().endsWith('.pdf')"
            :src="getPdfPreviewUrl(file)"
            class="preview-iframe"
          />
          
          <!-- Office文件预览（使用HTML预览接口） -->
          <iframe
            v-else-if="file.fileType === 'document' && isOfficeFile(file.originalName)"
            :src="getOfficePreviewUrl(file)"
            class="preview-iframe"
          />
          
          <!-- TXT等文本文件预览 -->
          <div
            v-else-if="file.fileType === 'document' && isTextFile(file.originalName)"
            class="preview-text"
          >
            <pre class="text-content">{{ textContent }}</pre>
          </div>
          
          <!-- 其他文档类型（不支持预览） -->
          <div v-else-if="file.fileType === 'document'" class="preview-unsupported">
            <el-icon class="unsupported-icon">
              <Document />
            </el-icon>
            <p>此文件类型暂不支持在线预览</p>
            <el-button type="primary" @click="handleDownload">
              下载文件
            </el-button>
          </div>
          
          <!-- 其他文件类型 -->
          <div v-else class="preview-unsupported">
            <el-icon class="unsupported-icon">
              <Document />
            </el-icon>
            <p>此文件类型不支持预览</p>
            <el-button type="primary" @click="handleDownload">
              下载文件
            </el-button>
          </div>
        </div>
        
        <div v-else class="preview-unsupported">
          <el-icon class="unsupported-icon">
            <Document />
          </el-icon>
          <p>此文件类型不支持预览</p>
          <el-button type="primary" @click="handleDownload">
            下载文件
          </el-button>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
import { computed, watch, ref, onUnmounted } from 'vue'
import { Download, Share, Document, Loading } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import type { CdFileVo } from '@/types/cd'
import request from '@/utils/request'
import { fileApi } from '@/api/cd'

interface Props {
  visible: boolean
  file: CdFileVo | null
}

interface Emits {
  (e: 'update:visible', visible: boolean): void
  (e: 'download', file: CdFileVo): void
  (e: 'share', file: CdFileVo): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const dialogVisible = computed({
  get: () => props.visible,
  set: (value) => emit('update:visible', value)
})

// 预览图片URL
const imageUrl = ref<string>('')
// 文本内容
const textContent = ref<string>('')

// 判断是否为文本文件
const isTextFile = (filename: string): boolean => {
  const textExtensions = ['.txt', '.text', '.md', '.log', '.json', '.xml', '.html', '.css', '.js', '.vue', '.ts']
  const ext = filename.substring(filename.lastIndexOf('.')).toLowerCase()
  return textExtensions.includes(ext)
}

// 判断是否为Office文件
const isOfficeFile = (filename: string): boolean => {
  const officeExtensions = ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx']
  const ext = filename.substring(filename.lastIndexOf('.')).toLowerCase()
  return officeExtensions.includes(ext)
}

// 获取PDF预览URL（直接使用文件URL）
const getPdfPreviewUrl = (file: CdFileVo): string => {
  // PDF文件直接使用previewUrl（已指向下载接口）
  // 需要添加 /dev-api 前缀，让 Vite proxy 转发到后端
  const basePath = import.meta.env.VITE_APP_BASE_API || '/dev-api'
  const url = file.previewUrl || ''
  const fullUrl = url.startsWith('/') ? `${basePath}${url}` : `${basePath}/${url}`
  console.log('PDF预览URL:', fullUrl)
  return fullUrl
}

// 获取Office预览URL（使用HTML预览接口）
const getOfficePreviewUrl = (file: CdFileVo): string => {
  // Office文件使用HTML预览接口
  const basePath = import.meta.env.VITE_APP_BASE_API || '/dev-api'
  const previewUrl = `${basePath}/cd/file/preview-html/${file.fileId}`
  console.log('Office预览URL:', previewUrl)
  return previewUrl
}

// 监听文件变化，加载预览内容
watch(() => props.file, async (file, oldFile) => {
  // 先清理之前的内容
  if (imageUrl.value) {
    URL.revokeObjectURL(imageUrl.value)
    imageUrl.value = ''
  }
  textContent.value = ''
  
  if (file && file !== oldFile) {
    // 如果是图片，通过axios加载并创建blob URL
    if (file.fileType === 'image' && file.previewUrl) {
      try {
        const response = await request({
          url: file.previewUrl,
          method: 'get',
          responseType: 'blob'
        }) as Blob
        
        // 检查是否是JSON响应（错误）
        if (response.type === 'application/json' || response.size < 1000) {
          ElMessage.error('图片加载失败，可能没有权限或接口错误')
          imageUrl.value = ''
          return
        }
        
        // 创建blob URL
        imageUrl.value = URL.createObjectURL(response as Blob)
      } catch (error: any) {
        ElMessage.error('加载图片失败: ' + (error.message || '未知错误'))
        imageUrl.value = ''
      }
    } else if (file.fileType === 'document' && isTextFile(file.originalName) && file.previewUrl) {
      // 如果是文本文件，加载文本内容
      try {
        const response = await request({
          url: file.previewUrl,
          method: 'get',
          responseType: 'text'
        })
        textContent.value = response as unknown as string
      } catch (error: any) {
        ElMessage.error('加载文本文件失败: ' + (error.message || '未知错误'))
        textContent.value = ''
      }
    } else {
      imageUrl.value = ''
      textContent.value = ''
    }
  }
}, { immediate: true })

// 组件卸载时清理blob URL
onUnmounted(() => {
  if (imageUrl.value) {
    URL.revokeObjectURL(imageUrl.value)
  }
})

const handleDownload = async () => {
  if (!props.file) return
  try {
    const blob = await fileApi.download(props.file.fileId) as any as Blob
    // 处理文件下载
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = props.file.originalName || 'download'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
    ElMessage.success('文件下载成功')
    // 触发事件，让父组件也可以处理
    emit('download', props.file)
  } catch (error) {
    console.error('下载文件失败:', error)
    ElMessage.error('下载文件失败')
  }
}

const handleShare = () => {
  if (!props.file) return
  // 触发事件，让父组件打开分享对话框
  emit('share', props.file)
}

const handleImageLoad = (e: Event) => {
  // 图片加载成功
}

const handleImageError = (e: Event) => {
  ElMessage.error('图片加载失败')
}

const handleClose = () => {
  dialogVisible.value = false
}
</script>

<style scoped lang="scss">
.preview-container {
  height: 70vh;
  display: flex;
  flex-direction: column;
}

.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 16px;
  border-bottom: 1px solid #e4e7ed;
  
  h3 {
    margin: 0;
    font-size: 18px;
    font-weight: 500;
  }
  
  .preview-actions {
    display: flex;
    gap: 8px;
  }
}

.preview-content {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 16px;
}

.preview-area {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.preview-image {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.loading {
  text-align: center;
  
  .el-icon {
    font-size: 32px;
    color: var(--el-color-primary);
    margin-bottom: 16px;
  }
  
  p {
    margin: 0;
    color: var(--el-text-color-secondary);
  }
}

.preview-iframe {
  width: 100%;
  height: 100%;
  border: none;
}

.preview-text {
  width: 100%;
  height: 100%;
  overflow: auto;
  padding: 20px;
  background: #f5f5f5;
  
  .text-content {
    margin: 0;
    padding: 16px;
    background: white;
    border-radius: 4px;
    font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
    font-size: 14px;
    line-height: 1.6;
    white-space: pre-wrap;
    word-wrap: break-word;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  }
}

.preview-unsupported {
  text-align: center;
  
  .unsupported-icon {
    font-size: 64px;
    color: #c0c4cc;
    margin-bottom: 16px;
  }
  
  p {
    margin: 0 0 16px 0;
    color: #606266;
    font-size: 16px;
  }
  
  .tip {
    font-size: 14px;
    color: #909399;
    margin-bottom: 24px;
  }
}
</style>
